/*
 * Copyright 2017 JessYan
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.chcit.mobile.app.config;

import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.text.TextUtils;

import com.alibaba.fastjson.JSONObject;
import com.chcit.mobile.BuildConfig;
import com.chcit.mobile.common.HttpMethodContains;
import com.chcit.mobile.app.utils.SharedPreUtils;
import com.chcit.mobile.helper.HttpClientHelper;
import com.jess.arms.base.app.ConfigKeys;
import com.jess.arms.base.app.Quick;
import com.jess.arms.di.component.AppComponent;
import com.jess.arms.http.GlobalHttpHandler;
import com.jess.arms.http.log.RequestInterceptor;
import com.jess.arms.utils.ArmsUtils;

import java.io.IOException;

import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;

import static java.net.HttpURLConnection.HTTP_OK;


/**
 * ================================================
 * 展示 {@link GlobalHttpHandler} 的用法
 * <p>
 * Created by JessYan on 04/09/2017 17:06
 * <a href="mailto:jess.yan.effort@gmail.com">Contact me</a>
 * <a href="https://github.com/JessYanCoding">Follow me</a>
 * ================================================
 */
public class GlobalHttpHandlerImpl implements GlobalHttpHandler {
    private Context context;

    public GlobalHttpHandlerImpl(Context context) {
        this.context = context;
    }

    /**
     * 这里可以先客户端一步拿到每一次 Http 请求的结果, 可以先解析成 Json, 再做一些操作, 如检测到 token 过期后
     * 重新请求 token, 并重新执行请求
     *
     * @param httpResult 服务器返回的结果 (已被框架自动转换为字符串)
     * @param chain {@link okhttp3.Interceptor.Chain}
     * @param response {@link Response}
     * @return
     */
    @Override
    public Response onHttpResultResponse(@Nullable String httpResult, @NonNull Interceptor.Chain chain, @NonNull Response response) {
        if (!TextUtils.isEmpty(httpResult)) {
            if( RequestInterceptor.isJson(response.body().contentType())){
                return  response;
            }

            if(RequestInterceptor.isText(response.body().contentType())&&httpResult.contains("会话超时或未登录")){
                AppComponent appComponent = ArmsUtils.obtainAppComponentFromContext(Quick.getApplicationContext());
               /* okhttp3.OkHttpClient.Builder ClientBuilder=new okhttp3.OkHttpClient.Builder();
                ClientBuilder.readTimeout(20, TimeUnit.SECONDS);//读取超时
                ClientBuilder.connectTimeout(6, TimeUnit.SECONDS);//连接超时
                ClientBuilder.writeTimeout(60, TimeUnit.SECONDS);//写入超时
                ClientBuilder.cookieJar(new MyCookiesManager());*/
                String params = "?userName="+HttpClientHelper.getUserName()+"&&password="+HttpClientHelper.getPassword();
                Request request = new Request
                        .Builder()
                        .url(SharedPreUtils.getInstance().getBaseUrl()+HttpMethodContains.LOGIN_QUERY_URL+params)
                        .method("GET", null)
                        .build();
                try {
                   Response newResponse =   appComponent.okHttpClient().newCall(request).execute();
                   JSONObject result = JSONObject.parseObject( newResponse.body().string());
                    Quick.withConfigure(ConfigKeys.TOKEN,result.getString("chcToken"));
                    Request newRequest = chain.request().newBuilder()
                            .build();
                    response = appComponent.okHttpClient().newCall(newRequest).execute();
                    if (response.code() == HTTP_OK) {

                        assert response.body() != null;
                        return new Response.Builder()
                                .code(200)
                                .addHeader("Content-Type", "application/json")
                                .body(ResponseBody.create(MediaType.parse("application/json"),response.body().string()))
                                .message("OK")
                                .request(chain.request())
                                .protocol(Protocol.HTTP_1_1)
                                .build();
                    }
                    return response;


                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

        /* 这里如果发现 token 过期, 可以先请求最新的 token, 然后在拿新的 token 放入 Request 里去重新请求
        注意在这个回调之前已经调用过 proceed(), 所以这里必须自己去建立网络请求, 如使用 Okhttp 使用新的 Request 去请求
        create a new request and modify it accordingly using the new token
        Request newRequest = chain.request().newBuilder().header("token", newToken)
                             .build();

        retry the request

        response.body().close();
        如果使用 Okhttp 将新的请求, 请求成功后, 再将 Okhttp 返回的 Response return 出去即可
        如果不需要返回新的结果, 则直接把参数 response 返回出去即可*/
        return response;
    }

    /**
     * 这里可以在请求服务器之前拿到 {@link Request}, 做一些操作比如给 {@link Request} 统一添加 token 或者 header 以及参数加密等操作
     *
     * @param chain {@link okhttp3.Interceptor.Chain}
     * @param request {@link Request}
     * @return
     */
    @Override
    public Request onHttpRequestBefore(Interceptor.Chain chain, Request request) {
        /* 如果需要再请求服务器之前做一些操作, 则重新返回一个做过操作的的 Request 如增加 Header, 不做操作则直接返回参数 request

        return chain.request().newBuilder().header("token", tokenId)
                              .build(); */
        if(BuildConfig.LOG_DEBUG && SharedPreUtils.getInstance().getBoolean(ConfigKeys.TEST_MODE.name(),false)){
            return request;
        }
        final String url = chain.request().url().toString();
        Request.Builder requestBuild = request.newBuilder()
                .header("Accept-Language", "zh")
                .header("x-requested-with", "XMLHttpRequest");
        if(url.contains(HttpMethodContains.LOGIN_QUERY_URL)){
            return request;
        }else //if(url.contains(HttpMethodContains.REQUEST_QUERY_URL)||url.contains(HttpMethodContains.STORAGE_URL))
            {
            String token =  Quick.getToken();
               /* String appSessionID = Quick.getAppSessionId();
                Request oldRequest = chain.request();
                Request.Builder newRequestBuild = oldRequest.newBuilder();;
                String method = oldRequest.method();
                String postBodyString="";
                if("POST".equals(method)) {
                    RequestBody oldBody = oldRequest.body();
                    if (oldBody instanceof FormBody) {
                        FormBody.Builder formBodyBuilder = new FormBody.Builder();
                        formBodyBuilder.add("appSessionID", appSessionID);

                        RequestBody formBody = formBodyBuilder.build();
                        postBodyString = bodyToString(oldRequest.body());
                        postBodyString += ((postBodyString.length() > 0) ? "&" : "") + bodyToString(formBody);
                        newRequestBuild.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"), postBodyString));
                    }
                }*/;
                if(!token.isEmpty()){
                    requestBuild.header("chcToken", token);

                }

                if(HttpClientHelper.getSelectWareHouse() != null){
                    requestBuild.addHeader("warehouseId",String.valueOf(HttpClientHelper.getSelectWareHouse().getId()));
                }
             return    requestBuild.build();
        }/*else {
            String appSessionID = Quick.getAppSessionId();
            Request oldRequest = chain.request();
            Request.Builder newRequestBuild=null;
            String method = oldRequest.method();
            String postBodyString="";
            if("POST".equals(method)){
                RequestBody oldBody = oldRequest.body();
                if(oldBody instanceof FormBody) {
                    FormBody.Builder formBodyBuilder = new FormBody.Builder();
                    formBodyBuilder.add("appSessionID", appSessionID);
                    newRequestBuild = oldRequest.newBuilder();
                    RequestBody formBody = formBodyBuilder.build();
                    postBodyString = bodyToString(oldRequest.body());
                    postBodyString += ((postBodyString.length() > 0) ? "&" : "") + bodyToString(formBody);
                    newRequestBuild.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"), postBodyString));
                }else if(oldBody instanceof MultipartBody){
                    MultipartBody oldBodyMultipart = (MultipartBody)oldBody;
                    List<MultipartBody.Part> oldPartList = oldBodyMultipart.parts();
                    MultipartBody.Builder builder = new MultipartBody.Builder();
                    builder.setType(MultipartBody.FORM);
                    RequestBody requestBody1 = RequestBody.create(MediaType.parse("text/plain"), iCommon.DEVICE_OS);
                    RequestBody requestBody2 = RequestBody.create(MediaType.parse("text/plain"), Utils.instance().getAppNameNew());
                    RequestBody requestBody3 = RequestBody.create(MediaType.parse("text/plain"), Utils.instance().getAppVersionName());
                    for (MultipartBody.Part part:oldPartList) {
                        builder.addPart(part);
                        postBodyString += (bodyToString(part.body()) + "\n");
                    }
                    postBodyString += (bodyToString(requestBody1) + "\n");
                    postBodyString += (bodyToString(requestBody2) + "\n");
                    postBodyString += (bodyToString(requestBody3) + "\n");
              builder.addPart(oldBody);  //不能用这个方法，因为不知道oldBody的类型，可能是PartMap过来的，也可能是多个Part过来的，所以需要重新逐个加载进去
                    builder.addPart(requestBody1);
                    builder.addPart(requestBody2);
                    builder.addPart(requestBody3);
                    newRequestBuild = oldRequest.newBuilder();
                    newRequestBuild.post(builder.build());
                    Log.e(TAG,"MultipartBody,"+oldRequest.url());
                }else{
                    newRequestBuild = oldRequest.newBuilder();
                }
            }else {
                // 添加新的参数
                HttpUrl.Builder commonParamsUrlBuilder = oldRequest.url()
                        .newBuilder()
                        .scheme(oldRequest.url().scheme())
                        .host(oldRequest.url().host())
                        .addQueryParameter("appSessionID",appSessionID);

                newRequestBuild = oldRequest.newBuilder()
                        .method(oldRequest.method(), oldRequest.body())
                        .url(commonParamsUrlBuilder.build());
            }

           return newRequestBuild
                    .addHeader("Accept-Language", "zh")
                    .build();

         *//*   long startTime = System.currentTimeMillis();
            okhttp3.Response response = chain.proceed(newRequest);
            long endTime = System.currentTimeMillis();
            long duration = endTime - startTime;
            okhttp3.MediaType mediaType = response.body().contentType();
            String content = response.body().string();*//*
           *//*  int httpStatus = response.code();
           StringBuilder logSB = new StringBuilder();
            logSB.append("-------start:"+method+"|");
            logSB.append(newRequest.toString()+"\n|");
            logSB.append(method.equalsIgnoreCase("POST")?"post参数{"+ postBodyString +"}\n|":"");
            logSB.append("httpCode=" + httpStatus + ";Response:" + content+"\n|");
            logSB.append("----------End:" + duration + "毫秒----------");

              return response.newBuilder()
                    .body(okhttp3.ResponseBody.create(mediaType, content))
                    .build();
            *//*


        }
*/
    }
    private  String bodyToString(final RequestBody request) {
        try {
            final RequestBody copy = request;
            final Buffer buffer = new Buffer();
            if (copy != null)
                copy.writeTo(buffer);
            else
                return "";
            return buffer.readUtf8();
        } catch (final IOException e) {
            return "did not work";
        }
    }



}
